package com.feiuxiu.datastructure.linklist;


import java.util.NoSuchElementException;

/**
 * description: 单向链表实现
 * author: feixiu
 * date:2025/9/9 11:03
 */
public class MyLinkedList2<E> {

    private static class Node<E>{
        E val;
        Node<E> next;

        public Node(E val) {
            this.val = val;
        }
    }
    //虚拟头节点
   private Node<E> head;

    //实际的尾部指针调用
   private Node<E> tail;

    private int size;
    // 构造函数初始化虚拟头尾节点
    public MyLinkedList2() {
        this.head=new Node<>(null);
        this.tail=head;
        this.size=0;
    }

    // 增
    public void  addLast(E e){
        Node<E> x=new Node<>(e);
        tail.next=x;
        tail=x;
        size++;
    }

    public void  addFirst(E e){
        Node<E> x=new Node<>(e);
        //首先让虚拟头节点指向x
        x.next=head.next;
        head.next=x;
        //然后判断是不是插入的第一个元素，如果是的话，还要让tail 移动
        if (size==0){
            tail=x;//tail 移动到尾部
        }
        size++;
    }

    public void add(int index,E element){
        // 判断插入位置是否合法
        checkPositionIndex(index);
        if (index==size){
            addLast(element);
            return;
        }
        // 单向链表插入，需要先找到对应index的前一个节点

        Node<E> prev = head;
        for (int i = 0; i < index; i++) {
            prev=prev.next;
        }

        Node<E> x = new Node<>(element);
        x.next=prev.next;
        prev.next=x;

        size++;
    }




    //删除


    public E removeFirst(){
        //判断是不是空
        if (size==0){
            throw new NoSuchElementException();
        }
        Node<E> x = head.next;
        head.next=x.next;
        x.next=null;
        size--;
        //当数组里面没有元素的时候，需要让tail 指向head
        if (size==0){
            tail=head;
        }
        return x.val;
    }

    public E removeLast(){
        //判断是不是空
        if (size==0){
            throw new NoSuchElementException();
        }
        Node<E> prev = head;
        while (prev.next!=tail){
            prev=prev.next;
        }
        Node<E> x = prev.next;
        prev.next=null;
        tail=prev;
        size--;
        return x.val;

    }

    public E remove(int index){
        checkElementIndex(index);
        //判断删除的是不是最后一个元素
        if (index==size-1){
            return removeLast();

        }
        Node<E> prev = head;
        for (int i = 0; i < index; i++) {
            prev=prev.next;
        }
        Node<E> x = prev.next;
        prev.next=x.next;
        x.next=null;


        size--;
        return x.val;

    }




    //查
    public E get(int index){
        checkElementIndex(index);
        Node<E> x = getNode(index);
        return x.val;
    }
    public E getFirst(){
        checkElementIndex(0);
        return head.next.val;

    }
    public E getLast(){
        checkElementIndex(0);
        return tail.val;
    }


    //修改
    public E set(int index,E element){
        checkElementIndex(index);
        Node<E> x = getNode(index);
        E oldVal=x.val;
        x.val=element;
        return oldVal;
    }


        //工具

    private Node<E> getNode(int index) {
        checkElementIndex(index);
        Node<E> p = head.next;

        for (int i = 0; i < index; i++) {
            p=p.next;
        }
        return p;
    }

    private boolean isElementIndex(int index) {
        return index >= 0 && index < size;
    }

    private boolean isPositionIndex(int index) {
        return index >= 0 && index <= size;
    }

    //检查index 索引位置是否可以存在元素
    private void checkElementIndex(int index){
        if (!isElementIndex(index))
            throw new IndexOutOfBoundsException("Index: "+index +", Size: "+size);
    }
    //检查index 索引位置是否可以添加元素
    private void checkPositionIndex(int index){
        if (!isPositionIndex(index))
            throw new IndexOutOfBoundsException("Index: "+index +", Size: "+size);
    }
    private void display() {
        System.out.println("size = " + size);
        for (Node<E> p = head; p != tail; p = p.next) {
            System.out.print(p.next.val + " -> ");
        }
        System.out.println("null");
        System.out.println();
    }

    public static void main(String[] args) {
        MyLinkedList2<Integer> list = new MyLinkedList2<>();
        list.addFirst(1);
        list.addFirst(2);
        list.addLast(3);
        list.display();
        list.addLast(4);
        list.display();
        list.add(2, 5);

        list.display();
        System.out.println(list.removeFirst()); // 2
        System.out.println(list.removeLast()); // 4
        System.out.println(list.remove(1)); // 5

        System.out.println(list.getFirst()); // 1
        System.out.println(list.getLast()); // 3
        System.out.println(list.get(1)); // 3
    }

}
